PC 4K Intro minify テクニック by よっしん
#4k #Minification #圧縮 #Entity_Talk
https://youtu.be/JsNNMjP46ys?si=JWlAHT9NyOZWsU_t
よっしんによる、Windows 4kのMinificationテクニック集
Tokyo Demo Fest 2021におけるセミナー
本セミナーにおける知見の結晶がMinimalGLというフレームワークとして提供されている
内容
Demo・4kの概要
(略)
近年は4kはおてがるカテゴリ
4kの作り方
シェーダーをフル活用する
サウンドには4klang・Oidos等が使われるほか、シェーダで作ることも可能
Shader Minifier・Crinkler等を使ってMinificationを行う
Shader Minifierについて
4kに特化した定番minifier
一部シェーダの文法(マクロ・構造体等)に対応していない
2021年当時ではCompute Shaderに対応していないので、小細工が必要
Crinklerについて
4kに特化した定番exe packer
Visual C++のリンカとして動作する
高い圧縮率を得るためTips
似たバイト値が近くにある
完全一致する長いバイト列がある
バイト値の種類が少ない
なので、実践として
副作用のない命令の順序をいい感じに並び替える
なるべく既出の命令を使う
Crinklerが起動するまで
exeがメモリ上に展開される
_Import というcrinklerが自動的に付加する120バイトほどの処理を実行、 opengl32.dll や user32.dll 等のAPIアドレスを取得し、ユーザプログラムから使えるようにする
ユーザプログラムを実行、 _entrypoint というシンボルから開始
Crinklerの推奨オプション
/REPORT
/COMPMODE:SLOW
/HASHSIZE:300
/HASHTRIES:300
/ORDERTRIES:300
/UNSAFEIMPORT
/OVERRIDEALIGNMENTS
/UNALIGNCODE
/NOINITIALIZERS
/TINYIMPORT は非推奨。将来的なDLLのアップデートによりAPIアドレスを表すハッシュ値がコリジョンしやすい
人の手による温かみのあるminify
Shader MinifierとCrinklerを使ってがんばる
Sizecoding・Code golfの知見を用いる
Crinklerの /REPORT オプションで吐き出されるHTMLファイルを見ながらがんばる
シェーダコードのminify tips
Shader Minifierは万能ではないので、手動でMinifyを行う
つぶやきGLSLの知見に学ぶ
とはいえ、Crinklerで圧縮する場合、トリッキーな書き方をするより短く素直なコードを目指したほうが有利
関数オーバーロードを使おう
定義済みシンボルを使い回す
変数名の使用傾向を統一する。for文の i ・座標の p など
int 型を float 型に統一してみる
min(...min(...min(...))) は min(min(min(...)...)...) のほうが効率が良い
ネイティブコードのminify tips
実行ファイル全体をアセンブラ言語で記述する。C言語・C++のオーバーヘッドを削る
なるべく短い命令を使う
レジスタの0クリアは XOR を使う
レジスタ値代入は2バイト使うが、レジスタ値交換は1バイトで済む
単純な命令の組み合わせで圧縮効率化
MOV を PUSH ・ POP で置き換えたり
レジスタの使用傾向を統一する
PUSH は毎回同じレジスタを使うとか
_entrypoint のレジスタ初期値をabuseする
ECX レジスタは初期値は必ず 0 が入っているなど
自力でAPIアドレスを取得するほうが有利なこともある
Win32 APIの戻り値を使う。EAXレジスタに1を返すAPIは貴重
pre push。関数呼び出し時の引数pushをあらかじめしておく
undocumentedなAPI使用をabuse。過去バージョンとの互換性のために残されている謎仕様
省略して良いAPIを探す
OpenGLの不要なバインドとか
TODO: 内容まとめる